package com.rg.util;

import java.util.Scanner;

public class Calculate{
   private String str;
   private char exp[];
   private int length;

   Calculate(){
      exp = new char[100];
      length = 0;
   }

   String getExp(){
      return str;
   }

   void initExpression(){
      int i = 0, slength;
      
      System.out.println( "Please input a expression:");
      Scanner reader = new Scanner(System.in);
      String s = reader.nextLine();
      str = new String(s);
      slength = s.length();

      while(i < slength){
         if(s.charAt(i) == ' '){
             i++;
             continue;
         }
         exp[length] = s.charAt(i);
         length++;
         i++;
      }
   }

   boolean verifyExpression(){
      int i = 0;

      if(exp[i] == '(' || (exp[i] >= '0'&&exp[i] <= '9')){
         while(i < length){
            if(exp[i] == '('){
                if(exp[i + 1]<'0' || exp[i + 1]>'9')
                    return false;
            }
            else if(exp[i] >= '0' && exp[i] <= '9'){
                if((exp[i+1]<'0'||exp[i+1]>'9')&&exp[i+1]!='\0'&&exp[i+1]!='+'&&exp[i+1]!='-'&&exp[i+1]!='*'&&exp[i+1]!='/'&&exp[i+1]!=')')
                   return false;
            }
            else if(exp[i] == ')'){
                if(exp[i+1]!='+'&&exp[i+1]!='\0'&&exp[i+1]!='-'&&exp[i+1]!='*'&&exp[i+1]!='/'&&exp[i+1]!=')')
                    return false;
            }
            else{
                if((exp[i+1]<'0'||exp[i+1]>'9')&&exp[i+1]!='(')
                    return false;
            }
            i++;
         }

         Cstack_char brackets = new Cstack_char();

         i = 0;
         while(i < length){
            if(exp[i]=='('){
               brackets.push(exp[i]);
               i++;
            }
            else if(exp[i]==')'){
               if(!brackets.empty()){
                  brackets.pop();
                  i++;
                }
                else
                   return false;
            }
            else
                i++;
         }

         if(brackets.empty())
            return true;
         else
            return false;
      }
      else
         return false;
   }

   int expressionEvaluation(){
      Cstack_char oprStack = new Cstack_char();
      Cstack_int  numStack = new Cstack_int();
      int num,num1,num2,i = 0;
      char opr;

      while(exp[i] != '\0'){
         if(exp[i]>='0'&&exp[i]<='9'){
            num=(int)(exp[i]-'0');
            i++;
            while(exp[i]>='0'&&exp[i]<='9'){
               num = num*10+(int)(exp[i]-'0');
	       i++;
	    }
            numStack.push(num);
         }
         else{
            if(!oprStack.empty()){
               switch(exp[i]){
                  case '+':
                  case '-':
                  case '*':
                  case '/':
		     switch(precede(oprStack.peek(),exp[i])){
                        case -1:
                           oprStack.push(exp[i]);
			   i++;
                           break;
                        case 0:
                        case 1:
                           num2=numStack.pop();
                           num1=numStack.pop();
                           opr=oprStack.pop();
                           numStack.push(operate(num1,opr,num2));
                           oprStack.push(exp[i]);
                           i++;
                           break;
                     }
		     break;
                  case '(':
                     oprStack.push(exp[i]);
		     i++;
                     break;
                  case ')':
                     while(oprStack.peek()!='('){
                        num2=numStack.pop();
                        num1=numStack.pop();
                        opr=oprStack.pop();
                        numStack.push(operate(num1,opr,num2));
                     }
                     oprStack.pop();
		     i++;
                     break;
               }
            }
            else{
               oprStack.push(exp[i]);
	       i++;
	    }
         }
      }

      while(!oprStack.empty()){
         num2=numStack.pop();
         num1=numStack.pop();
         opr=oprStack.pop();
         numStack.push(operate(num1,opr,num2));
      }

      return numStack.peek();
   }
   
   int getIndex(char c){
      switch(c){
         case '(':
            return 0;
         case '+':
            return 1;
         case '-':
            return 1;
         case '*':
            return 2;
         case '/':
            return 2;
         default:
            return 3;
      }
   }

   int precede(char c1,char c2){
      if(getIndex(c1)-getIndex(c2)>0)
         return 1;
      else if(getIndex(c1)-getIndex(c2)==0)
         return 0;
      else
         return -1;
   }

   int operate(int num1,char ch,int num2){
      int result=0;

      switch(ch){
         case '+':
            result=num1+num2;
            break;
         case '-':
            result=num1-num2;
            break;
         case'*':
            result=num1*num2;
            break;
         case '/':
            result=num1/num2;
            break;
      }
      return result;
   }
}
